package shootplane;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * 界面类：窗口类JFrame-对象 面板/画板类JPanel - 不能直接new JPanel();
 */
public class ShootGame extends JPanel {
    //画板宽度和高度
    public static final int WIDTH = 400;//游戏界面的宽
    public static final int HEIGHT = 654;//游戏界面的高
    public static final int START = 0;//开始
    public static final int RUNNING = 1;//运行
    public static final int PAUSE = 2;//暂停
    public static final int GAMEOVER = 3;//游戏结束
    private int state;//游戏状态
    private int score = 0;//游戏分数
    private int difficultType = 1;//游戏难度
    private int difficultShootSpeed = 60;//大飞机射击速度
    private int difficult = 50;//飞行物生成速度
    private int countAirplane = 0;//计数击杀小飞机数量
    private int countBigplane = 0;//计数击杀大飞机数量
    private int countBee = 0;//计数击杀小蜜蜂数量
    private Hero hero;//英雄机
    private FlyObject[] flyings = {};// 用于存放敌机+小蜜蜂
    private Bullet[] bullets = {};// 用于存放英雄机子弹
    private BulletEnemy[] bullets2 = {};// 用于存放大敌机子弹
    private Ember[] embers = {};//用于存放灰烬
    // 定义所有的图片资源
    public static BufferedImage hero0Img;
    public static BufferedImage hero1Img;
    public static BufferedImage hero_ember0Img;
    public static BufferedImage hero_ember1Img;
    public static BufferedImage hero_ember2Img;
    public static BufferedImage hero_ember3Img;
    public static BufferedImage beeImg;
    public static BufferedImage bee_ember0Img;
    public static BufferedImage bee_ember1Img;
    public static BufferedImage bee_ember2Img;
    public static BufferedImage bee_ember3Img;
    public static BufferedImage bulletImg;
    public static BufferedImage airplaneImg;
    public static BufferedImage airplane_ember0Img;
    public static BufferedImage airplane_ember1Img;
    public static BufferedImage airplane_ember2Img;
    public static BufferedImage airplane_ember3Img;
    public static BufferedImage bigplaneImg;
    public static BufferedImage bigplane_ember0Img;
    public static BufferedImage bigplane_ember1Img;
    public static BufferedImage bigplane_ember2Img;
    public static BufferedImage bigplane_ember3Img;
    public static BufferedImage background;
    public static BufferedImage startImg;
    public static BufferedImage pauseImg;
    public static BufferedImage gameoverImg;
    public static BufferedImage luFuImg;

    static {// 加载图片资源
//		String path = Hero.class.getResource("hero0.png").getFile();
        try {// read静态方法
            background = ImageIO.read(Hero.class.getResource("background.png"));
            hero0Img = ImageIO.read(Hero.class.getResource("hero0.png"));
            hero1Img = ImageIO.read(Hero.class.getResource("hero1.png"));
            hero_ember0Img = ImageIO.read(Hero.class.getResource("hero_ember0.png"));
            hero_ember1Img = ImageIO.read(Hero.class.getResource("hero_ember1.png"));
            hero_ember2Img = ImageIO.read(Hero.class.getResource("hero_ember2.png"));
            hero_ember3Img = ImageIO.read(Hero.class.getResource("hero_ember3.png"));
            beeImg = ImageIO.read(Hero.class.getResource("bee.png"));
            bee_ember0Img = ImageIO.read(Hero.class.getResource("bee_ember0.png"));
            bee_ember1Img = ImageIO.read(Hero.class.getResource("bee_ember1.png"));
            bee_ember2Img = ImageIO.read(Hero.class.getResource("bee_ember2.png"));
            bee_ember3Img = ImageIO.read(Hero.class.getResource("bee_ember3.png"));
            bulletImg = ImageIO.read(Hero.class.getResource("bullet.png"));
            airplaneImg = ImageIO.read(Hero.class.getResource("airplane.png"));
            airplane_ember0Img = ImageIO.read(Hero.class.getResource("airplane_ember0.png"));
            airplane_ember1Img = ImageIO.read(Hero.class.getResource("airplane_ember1.png"));
            airplane_ember2Img = ImageIO.read(Hero.class.getResource("airplane_ember2.png"));
            airplane_ember3Img = ImageIO.read(Hero.class.getResource("airplane_ember3.png"));
            bigplaneImg = ImageIO.read(Hero.class.getResource("bigplane.png"));
            bigplane_ember0Img = ImageIO.read(Hero.class.getResource("bigplane_ember0.png"));
            bigplane_ember1Img = ImageIO.read(Hero.class.getResource("bigplane_ember1.png"));
            bigplane_ember2Img = ImageIO.read(Hero.class.getResource("bigplane_ember2.png"));
            bigplane_ember3Img = ImageIO.read(Hero.class.getResource("bigplane_ember3.png"));
            startImg = ImageIO.read(Hero.class.getResource("start.png"));
            pauseImg = ImageIO.read(Hero.class.getResource("pause.png"));
            gameoverImg = ImageIO.read(Hero.class.getResource("gameover.png"));
            luFuImg = ImageIO.read(Hero.class.getResource("lufu.jpg"));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public ShootGame() {// 测试
        // 创建英雄机
        hero = new Hero();
    }

    // 绘画的方法 - JPanel父类给的 - 重写
    // setVisiable(true)-自动调用paint
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // 自定义绘画方法
        // 图片对象:image x坐标 y坐标 null
        g.drawImage(background, 0, 0, null);//画背景
        paintAll(g);
        g.drawImage(hero.getImage(), hero.getX(), hero.getY(), null);//画英雄机
        paintFlyObject(g);//画敌机+小蜜蜂
        paintBullets(g);//画子弹
        paintBulletEnemy(g);//画敌机子弹
        paintEmbers(g);//画爆炸效果
        paintState(g);//画状态
        // 字符串 x坐标 y坐标
        g.setColor(new Color(255, 255, 0));//设置颜色
        Font font = new Font("宋体", Font.BOLD, 15);//字体、风格：三个常量IFont.PLAIN,Font.BOLD,Font.ITALIC、字号
        setFont(font);
        g.drawString("SCORE：" + score, 10, 15);//画分数
        g.drawString("LIFE：" + hero.getLife(), 10, 30);//画生命
        paintDifficult(g);//画难度
        g.drawString("小飞机：" + countAirplane, 10, 580);//画击杀小飞机数量
        g.drawString("大敌机：" + countBigplane, 10, 595);//画击杀大敌机数量
        g.drawString("小蜜蜂：" + countBee, 10, 610);//画击杀小蜜蜂数量
        g.drawString("awardType：" + hero.getAwardType(), 250, 610);//奖励数量

    }

    // 画飞行物：画敌机+小蜜蜂flyings
    private void paintFlyObject(Graphics g) {
        for (int i = 0; i < flyings.length; i++) {
            g.drawImage(flyings[i].getImage(), flyings[i].getX(), flyings[i].getY(), null);
        }

    }

    // 画子弹
    private void paintBullets(Graphics g) {
        for (int i = 0; i < bullets.length; i++) {
            g.drawImage(bullets[i].getImage(), bullets[i].getX(), bullets[i].getY(), null);
        }

    }

    //画地方子弹
    private void paintBulletEnemy(Graphics g) {
        for (int i = 0; i < bullets2.length; i++) {
            g.drawImage(bullets2[i].getImage(), bullets2[i].getX(), bullets2[i].getY(), null);
        }

    }

    //画状态
    private void paintState(Graphics g) {
        switch (state) {
            case START:
                g.drawImage(startImg, 0, 0, null);
                break;
            case PAUSE:
                g.drawImage(pauseImg, 0, 0, null);
                break;
            case GAMEOVER:
                g.drawImage(gameoverImg, 0, 0, null);
                break;
        }
    }
    //画难度

    public void paintDifficult(Graphics g) {
        switch (difficultType) {
            case 1:
                g.drawString("难度：1", 10, 45);
                break;
            case 2:
                g.drawString("难度：2", 10, 45);
                break;
            case 3:
                g.drawString("难度：3", 10, 45);
                break;
            case 4:
                g.drawString("难度：4", 10, 45);
                break;
            case 5:
                g.drawString("难度：5", 10, 45);
                break;
            case 6:
                g.drawString("难度：6", 10, 45);
                break;
        }
    }

    //画爆炸效果
    public void paintEmbers(Graphics g) {
        for (int i = 0; i < embers.length; i++) {
            g.drawImage(embers[i].fly.getImage(), embers[i].fly.getX(), embers[i].fly.getY(), null);
        }
    }

    //画清屏效果
    public void paintAll(Graphics g) {
        if (countClick >= 3) {
            g.drawImage(luFuImg, -500, 0, null);
        }
    }

    /**
     * 开始游戏：定时器-持续性、周期性
     * 生成敌机、小蜜蜂 -> 飞行物
     * 生成子弹 -> 英雄机
     * 移动 -> 飞行物
     * 判断游戏是否结束
     * 判断飞行物和子弹有没有撞击
     * 判断英雄机和飞行物有没有撞击
     * 判断子弹有没有出界
     * 判断飞行物有没有出界
     */
    // 定时器
    Timer timer = new Timer();
    //清屏效果
    private int countClick = 0;
    private long time1 = 0;
    private long time2 = 0;

    // 开始游戏
    public void action() {
        //匿名内部类方式实现监听
        MouseAdapter ma = new MouseAdapter() {
            //鼠标单击时调用
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                switch (state) {
                    case START:
                        state = RUNNING;
                        break;
                    case GAMEOVER:
                        //全部清空归0
                        hero = new Hero();
                        flyings = new FlyObject[0];
                        bullets = new Bullet[0];
                        bullets2 = new BulletEnemy[0];
                        state = START;
                        score = 0;
                        countAirplane = 0;
                        countBee = 0;
                        countBigplane = 0;
                        difficultShootSpeed = 60;
                        difficultType = 1;
                        break;
                    case RUNNING://清屏效果（生命-1）
                        if (countClick < 3) {
                            time1 = System.currentTimeMillis();
                            countClick++;
                        } else {
                            time2 = System.currentTimeMillis();
                            countClick = 0;
                        }
                        if (Math.abs(time2 - time1) <= 500) {
//                            flyings = new FlyObject[0];
//                            bullets2 = new BulletEnemy[0];
//                            System.out.println("清屏");
                            hero.setLife(hero.getLife() - 1);//作弊器：快速点击三下鼠标，攻击最大化
                            hero.setAwardType(80);
                            time1 = 0;
                            time2 = 0;
                        }
                }
            }

            //鼠标进入时调用
            @Override
            public void mouseEntered(MouseEvent e) {
                super.mouseEntered(e);
                if (state == PAUSE) {
                    state = RUNNING;
                }
            }

            //鼠标移出时调用
            @Override
            public void mouseExited(MouseEvent e) {
                super.mouseExited(e);
                if (state != GAMEOVER && state != START) {
                    state = PAUSE;
                }
            }

            //鼠标移动时调用
            @Override
            public void mouseMoved(MouseEvent e) {
                super.mouseMoved(e);
                if (state == RUNNING) {
                    hero.setX(e.getX() - hero.getWidth() / 2);
                    hero.setY(e.getY() - hero.getHeight() / 2);
                    repaint();
                }
            }
        };
        //添加鼠标事件
        this.addMouseListener(ma);
        this.addMouseMotionListener(ma);
        // 过1s后开始执行，每0.1s执行一次
        timer.schedule(new TimerTask() {
            // 周期性任务
            @Override
            public void run() {
                if (state == RUNNING) {
                    //生成飞行物
                    enterFlyObject();
                    //生成子弹
                    shootAction();
                    //移动
                    goFlyings();
                    //子弹与飞行物撞击
                    crashBulletAndFlyings();
                    //英雄机与飞行物撞击
                    crashHeroFlyings();
                    //英雄机和大飞机子弹撞击
                    crashBulletEnemy();
                    //清理出界
                    outOfBoundsAction();
                    //爆炸效果
                    goEmber();
                    //检查游戏是否结束
                    checkGame();
                }
                //界面刷新
                repaint();
            }

        }, 100, 20);
    }

    private int countFlyings = 0;//定时

    // 生成敌机、小蜜蜂 -> flyings
    private void enterFlyObject() {
        countFlyings++;
        if (score > 5000) {
            difficultShootSpeed = 10;//大飞机射击速度
            difficultType = 6;//游戏难度
            difficult = 5;//飞行物生成速度
        } else if (score > 3000) {
            difficultShootSpeed = 30;//大飞机射击速度
            difficultType = 5;//游戏难度
            difficult = 20;//飞行物生成速度
        } else if (score > 1500) {
            difficultShootSpeed = 60;
            difficultType = 4;
            difficult = 30;
        } else if (score > 500) {
            difficultShootSpeed = 60;
            difficultType = 3;
            difficult = 30;
        } else if (score > 200) {
            difficultShootSpeed = 60;
            difficultType = 2;
            difficult = 50;
        } else {
            difficultShootSpeed = 60;
            difficultType = 1;
            difficult = 60;
        }
        if (countFlyings % difficult == 0) {
            int random = (int) (Math.random() * 15);
            FlyObject newFly;
            if (random == 0) {
                newFly = new Bee();
            } else if (random > 0 && random < 5) {
                newFly = new Bigplane();
            } else {
                newFly = new Airplane();
            }
            flyings = Arrays.copyOf(flyings, flyings.length + 1);
            flyings[flyings.length - 1] = newFly;
        }
    }

    //发射子弹
    private void shootAction() {
        if (countFlyings % hero.getShootSpeed() == 0) {
            Bullet[] newBullet = hero.shoot();
            bullets = Arrays.copyOf(bullets, bullets.length + newBullet.length);
            System.arraycopy(newBullet, 0, bullets, bullets.length - newBullet.length, newBullet.length);
        }
        if (difficultType >= 4) {
            if (countFlyings % difficultShootSpeed == 0) {
                for (int i = 0; i < flyings.length; i++) {
                    if (flyings[i] instanceof Bigplane) {
                        BulletEnemy newBullet = flyings[i].shootHero();
                        bullets2 = Arrays.copyOf(bullets2, bullets2.length + 1);
                        bullets2[bullets2.length - 1] = newBullet;
                    }
                }
            }
        }
    }

    //飞行物移动
    private void goFlyings() {
        for (int i = 0; i < flyings.length; i++) {
            flyings[i].move();
        }
        for (int i = 0; i < bullets.length; i++) {
            bullets[i].move();
        }
        for (int i = 0; i < bullets2.length; i++) {
            bullets2[i].move();
        }
        hero.move();
    }

    //清理过界
    private void outOfBoundsAction() {
        //判断飞行物
        for (int i = 0; i < flyings.length; i++) {
            if (flyings[i].getY() > HEIGHT) {
                hero.setAwardType(hero.getAwardType() / 2);//有飞机飞过界奖励减半
                FlyObject temp = flyings[i];
                flyings[i] = flyings[flyings.length - 1];
                flyings[flyings.length - 1] = temp;
                flyings = Arrays.copyOf(flyings, flyings.length - 1);
            }
        }
        //判断子弹
        for (int i = 0; i < bullets.length; i++) {
            if (bullets[i].getY() < -bullets[i].height) {
                Bullet temp = bullets[i];
                bullets[i] = bullets[bullets.length - 1];
                bullets[bullets.length - 1] = temp;
                bullets = Arrays.copyOf(bullets, bullets.length - 1);
            }
        }
        for (int i = 0; i < bullets2.length; i++) {
            if (bullets2[i].getY() > HEIGHT) {
                bullets2[i] = bullets2[bullets2.length - 1];
                bullets2 = Arrays.copyOf(bullets2, bullets2.length - 1);
            }
        }
    }

    //子弹与飞行物撞击
    private void crashBulletAndFlyings() {
        int flag = -1;//飞行物下标
        for (int i = 0; i < bullets.length; i++) {// i -> 子弹下标
            flag = crashBulletFlyings(bullets[i]);
            if (flag != -1) {
                flyings[flag].setFlood(flyings[flag].getFlood() - 1);
                if (flyings[flag].getFlood() == 0) {
                    //生成灰烬
                    Ember newEmber;
                    if (flyings[flag] instanceof Airplane) {
                        newEmber = new EmberAirplane(flyings[flag]);
                    } else if (flyings[flag] instanceof Bigplane) {
                        newEmber = new EmberBigplane(flyings[flag]);
                    } else {
                        newEmber = new EmberBee(flyings[flag]);
                    }
                    embers = Arrays.copyOf(embers, embers.length + 1);
                    embers[embers.length - 1] = newEmber;

                    if (flyings[flag] instanceof Airplane) {
                        Airplane a = (Airplane) flyings[flag];
                        countAirplane++;//判断击杀计数
                        score += a.getScore();//计分
                    } else if (flyings[flag] instanceof Bigplane) {
                        Bigplane a = (Bigplane) flyings[flag];
                        countBigplane++;//判断击杀计数
                        score += a.getScore();//计分
                        if (a.getAward() == 0) {//判断获得奖励
                            hero.setLife(hero.getLife() + 1);//加生命
                        } else {
                            hero.setAwardType(hero.getAwardType() + 1);//加攻击等级
                        }
                    } else {
                        Bee a = (Bee) flyings[flag];
                        countBee++;//判断击杀计数
                        if (a.getAward() == 0) {//判断获得奖励
                            hero.setLife(hero.getLife() + 1);//加生命
                        } else {
                            hero.setAwardType(hero.getAwardType() + 1);//加攻击等级
                        }
                    }
                    FlyObject temp = flyings[flag];//清除撞击物
                    flyings[flag] = flyings[flyings.length - 1];
                    flyings[flyings.length - 1] = temp;
                    flyings = Arrays.copyOf(flyings, flyings.length - 1);
                }

                Bullet temp2 = bullets[i];//清除撞击物
                bullets[i] = bullets[bullets.length - 1];
                bullets[bullets.length - 1] = temp2;
                bullets = Arrays.copyOf(bullets, bullets.length - 1);
            }
        }
    }

    private int crashBulletFlyings(Bullet bullet) {
        int flag = -1;//飞行物下标
        for (int i = 0; i < flyings.length; i++) {
            if (flyings[i].crashBullet(bullet)) {
                flag = i;//记录撞击飞行物
                break;
            }
        }
        return flag;
    }

    //英雄机与飞行物撞击
    private void crashHeroFlyings() {
        int flag = -1;//飞行物下标
        for (int i = 0; i < flyings.length; i++) {
            if (hero.crashFlyings(flyings[i])) {
                flag = i;//记录撞击飞行物
                break;
            }
        }
        if (flag != -1) {
            hero.setCheck(true);//显示爆炸效果
            hero.setLife(hero.getLife() - 1);//生命-1
            hero.setAwardType(hero.getAwardType() / 2);//清除奖励
            FlyObject temp = flyings[flag];//清除撞击物
            flyings[flag] = flyings[flyings.length - 1];
            flyings[flyings.length - 1] = temp;
            flyings = Arrays.copyOf(flyings, flyings.length - 1);
        }
    }

    //英雄机和子弹撞击
    private void crashBulletEnemy() {
        int flag = -1;//飞行物下标
        for (int i = 0; i < bullets2.length; i++) {
            if (hero.crashBulletEnemy(bullets2[i])) {
                flag = i;//记录撞击飞行物
                break;
            }
        }
        if (flag != -1) {
            hero.setCheck(true);//显示爆炸效果
            hero.setLife(hero.getLife() - 1);//生命-1
            hero.setAwardType(hero.getAwardType() / 2);//清除奖励
            bullets2[flag] = bullets2[bullets2.length - 1];//清除子弹
            bullets2 = Arrays.copyOf(bullets2, bullets2.length - 1);
        }
    }

    //爆炸效果
    public void goEmber() {
        for (int i = 0; i < embers.length; i++) {
            if (embers[i].getCount() >= 4) {
                embers[i] = embers[embers.length - 1];
                embers = Arrays.copyOf(embers, embers.length - 1);
            } else {
                embers[i].changeImg();
                embers[i].setCount(embers[i].getCount() + 1);
            }
        }
    }

    //判断游戏是否结束
    public void checkGame() {
        if (hero.getLife() <= 0) {
            state = GAMEOVER;
        }
    }

    // 创建窗口，初始化画板
    public void showMe() {
        JFrame window = new JFrame("飞机大战");
        // 设置窗口大小
        window.setSize(WIDTH, HEIGHT);
        // 设置窗口的关闭选项
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 设置初始位置 - 居中
        window.setLocationRelativeTo(null);// 居中
        // 将画板添加到窗口上
        window.add(this);
        window.setVisible(true);// 显示窗口，最后一步
    }

    public static void main(String[] args) {
        ShootGame s = new ShootGame();
        s.showMe();
        s.action();

    }
}